using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Diagnostics.Contracts;
using Konst3d.Efficiency.Suite;
using Konst3d.Efficiency;
using Efficiency.Controls;

namespace PEM
{
	// TOFIX: should be derived from MonitorsViewModel, or shared base class
	internal partial class CountersViewModel : ViewModelBase
	{
		#region Types

		internal delegate void EventHandler(ViewModelBase sender);

		internal enum FilterType
		{
			All,
			Active,
			Paused
		}

		#endregion // Types

		#region Events

		public event EventHandler SuiteOpened;
		public event EventHandler SuiteClosed;
		public event EventHandler SuiteCreated;
		public event EventHandler SuiteDeleted;
		public event EventHandler CounterSelected;

		#endregion // Events

		#region Properties

		public bool HasItems
		{
			get
			{
				return Suite != null ? Suite.Tasks.Count > 0 : false;
			}
		}

		public ObservableList2<IMonitor> Counters
		{
			get;
			private set;
		}

		public IEnumerable<FilterType> Filters
		{
			get;
			private set;
		}

		public FilterType Filter
		{
			get
			{
				return _filter;
			}
			set
			{
				if (_filter != value)
				{
					_filter = value;
					UpdateCounterList();
				}
			}
		}

		public IMonitor Selected
		{
			get
			{
				return _selected;
			}
			set
			{
				_selected = value;

				if (CounterSelected != null)
				{
					CounterSelected(this);
				}

				NotifyPropertyChanged("Selected");
			}
		}

		public CommandsCollection Commands
		{
			get;
			private set;
		}

		public IEfficiencySuite Suite
		{
			get
			{
				return _parentModel.Suite;
			}
		}

		#endregion // Properties

		#region Constructor

		public CountersViewModel(Window parentWindow, MainWindowViewModel parentModel)
		{
			Contract.Requires(parentWindow != null);
			Contract.Requires(parentModel  != null);

			_parentWindow = parentWindow;
			_parentModel = parentModel;

			_parentModel.SuiteOpened += OnSuiteOpened;
			_parentModel.SuiteClosed += OnSuiteClosed;
			_parentModel.SuiteCreated += OnSuiteCreated;
			_parentModel.SuiteDeleted += OnSuiteDeleted;

			Filters = new FilterType[] { FilterType.All, FilterType.Active, FilterType.Paused };

			Counters = new ObservableList2<IMonitor>();
			Commands = new CommandsCollection(this);

			_createEditCounterDlg = new CreateEditCounterDialog();
			_statisticDialog = new StatisticDialog();
		}

		#endregion // Constructor

		#region Overriden Methods

		protected override void DisposeManaged()
		{
			base.DisposeManaged();

			_createEditCounterDlg.Close();
			_createEditCounterDlg = null;

			_statisticDialog.Close();
			_statisticDialog = null;

			_parentModel.SuiteOpened -= OnSuiteOpened;
			_parentModel.SuiteClosed -= OnSuiteClosed;
			_parentModel.SuiteCreated -= OnSuiteCreated;
			_parentModel.SuiteDeleted -= OnSuiteDeleted;
			_parentModel = null;

			Counters.Clear();
		}

		#endregion // Overriden Methods

		#region Event Handlers

		private void OnSuiteOpened(MainWindowViewModel sender)
		{
			UpdateCounterList();

			if (SuiteOpened != null)
			{
				SuiteOpened(this);
			}
		}

		private void OnSuiteClosed(MainWindowViewModel sender)
		{
			UpdateCounterList();

			if (SuiteClosed != null)
			{
				SuiteClosed(this);
			}
		}

		private void OnSuiteCreated(MainWindowViewModel sender)
		{
			UpdateCounterList();

			if (SuiteCreated != null)
			{
				SuiteCreated(this);
			}
		}

		private void OnSuiteDeleted(MainWindowViewModel sender)
		{
			UpdateCounterList();

			if (SuiteDeleted != null)
			{
				SuiteDeleted(this);
			}
		}

		#endregion // Event Handlers

		#region Private Methods

		private void UpdateCounterList()
		{
			Counters.BeginUpdate();
			Counters.Clear();

			if (Suite != null)
			{
				foreach (var counter in Suite.Monitors)
				{
					if (IsCounterMutches(counter, _filter))
					{
						Counters.Add(counter);
					}
				}

				// Monitors.Sort(_comparers[_sorting]); -- any sorting here?
			}

			Counters.EndUpdate();
			NotifyPropertyChanged("Counters");
		}

		private static bool IsCounterMutches(IMonitor counter, FilterType filter)
		{
			Contract.Requires(counter != null);

			bool matches = false;

			if (counter.Type == MonitorType.Counter)
			{
				switch (filter)
				{
					case FilterType.All:
						matches = true;
						break;

					case FilterType.Active:
						matches = counter.Active;
						break;

					case FilterType.Paused:
						matches = !counter.Active;
						break;
				}
			}

			return matches;
		}

		#endregion // Private Methods

		#region Fields

		private Window _parentWindow;
		private MainWindowViewModel _parentModel;
		private FilterType _filter = FilterType.All;
		private IMonitor _selected;
		private CreateEditCounterDialog _createEditCounterDlg;
		private StatisticDialog _statisticDialog;

		#endregion // Fields
	}
}
